﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace PPC_emulator
{
    class RAM
    {
        MemoryStream mem1;
        public RAM()
        {
            byte[] buffer = new byte[25165824];
            for (int i = 0; i < 25165824; i++)
            {
                buffer[i] = 0;
            }
            mem1 = new MemoryStream(buffer, 0, 25165824, true, true);
        }

        public void setAddress32(uint address, uint value)
        {
            byte[] buffer = BitConverter.GetBytes(value);
            mem1.Position = (int)address - address%4;
            for (int i = 0; i < buffer.Length; i++)
            {
                mem1.WriteByte(buffer[i]);
            }
        }

        public void setAddress16(uint address, UInt16 value)
        {
            byte[] buffer = BitConverter.GetBytes(value);
            int pos = (int)(address - address % 2);
            pos += pos % 4 == 0 ? 2 : -2;  //tempfix
            mem1.Position = pos;
            for (int i = 0; i < buffer.Length; i++)
            {
                mem1.WriteByte(buffer[i]);
            }
        }

        public void setAddress8(uint address, byte value)
        {
            byte[] buffer = BitConverter.GetBytes(value);
            if (address % 4 == 0)  //this is wrong in so many ways ;_;
                mem1.Position = address + 3;
            else if (address % 4 == 1)
                mem1.Position = address + 1;
            else if (address % 4 == 2)
                mem1.Position = address - 1;
            else if (address % 4 == 3)
                mem1.Position = address - 3;
            for (int i = 0; i < buffer.Length; i++)
            {
                mem1.WriteByte(buffer[i]);
            }
        }

        public UInt32 getValue32(UInt32 address)
        {
            return (UInt32)BitConverter.ToInt32(mem1.GetBuffer(), (int)(address-(address%4)));
        }

        public UInt16 getValue16(UInt32 address)
        {
            if (address % 4 == 0)  //i should probably find out a better solution
                mem1.Position = address + 2;
            else if (address % 4 == 1)
                mem1.Position = address + 1; 
            else if (address % 4 == 2)
                mem1.Position = address - 2;
            else if (address % 4 == 3)
                mem1.Position = address - 3;
            String hexValue = "";
            hexValue += mem1.ReadByte().ToString("X1");
            hexValue = mem1.ReadByte().ToString("X1") + hexValue;
            return UInt16.Parse(hexValue, System.Globalization.NumberStyles.HexNumber);
        }

        public byte getValue8(UInt32 address)
        {
            if (address % 4 == 0)  // or just find the problem
                mem1.Position = address + 3;
            else if (address % 4 == 1)
                mem1.Position = address + 1; 
            else if (address % 4 == 2)
                mem1.Position = address - 1;
            else if (address % 4 == 3)
                mem1.Position = address - 3;
            String hexValue = mem1.ReadByte().ToString("X1");
            return byte.Parse(hexValue, System.Globalization.NumberStyles.HexNumber);
        }

        public byte[] getMiniStream(UInt32 start)
        {
            byte[] buffer = new byte[256];
            mem1.Position = (int)start;
            for (int i = 0; i < 256; i++)
            {
                buffer[i] = (byte) mem1.ReadByte();
            }
            return buffer;
        }
        
    }
}
